%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22marimo%22%2C%0A%23%20%20%20%20%20%22torch%22%2C%0A%23%20%20%20%20%20%22numpy%22%2C%0A%23%20%20%20%20%20%22matplotlib%22%2C%0A%23%20%20%20%20%20%22scipy%22%2C%0A%23%20%5D%0A%23%0A%23%20%5Btool.marimo.runtime%5D%0A%23%20auto_instantiate%20%3D%20false%0A%23%20on_cell_change%20%3D%20%22lazy%22%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.19.9%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20app_title%3D%22PINN%20for%201D%20Heat%20Equation%20(PyTorch)%22%2C%0A%20%20%20%20auto_download%3D%5B%22html%22%2C%20%22ipynb%22%5D%2C%0A)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Physics-Informed%20Neural%20Networks%20for%20PDEs%0A%20%20%20%20%23%23%20Solving%20the%201D%20Heat%20Equation%20Without%20Discretization%0A%0A%20%20%20%20**Physics-Informed%20Neural%20Networks%20(PINNs)**%20train%20neural%20networks%20to%20satisfy%20both%20governing%20equations%0A%20%20%20%20and%20boundary%2Finitial%20conditions%20simultaneously%E2%80%94no%20spatial%20or%20temporal%20discretization%20required.%0A%0A%20%20%20%20%7C%20Traditional%20PDE%20Methods%20%7C%20PINNs%20%7C%0A%20%20%20%20%7C------------------------%7C-------%7C%0A%20%20%20%20%7C%20Require%20spatial%20mesh%20%7C%20**Meshfree**%3A%20continuous%20solution%20everywhere%20%7C%0A%20%20%20%20%7C%20Fixed%20grid%20resolution%20%7C%20**Adaptive**%3A%20query%20at%20any%20%24(x%2Ct)%24%20%7C%0A%20%20%20%20%7C%20Discrete%20solutions%20%7C%20**Differentiable**%3A%20embed%20in%20optimization%20pipelines%20%7C%0A%20%20%20%20%7C%20Struggle%20with%20sparse%20data%20%7C%20**Data-efficient**%3A%20fuse%20physics%20with%20observations%20%7C%0A%0A%20%20%20%20**Navigation%3A**%20%5BJump%20to%20Control%20Panel%5D(%23control-panel)%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20The%20Physical%20System%0A%0A%20%20%20%20The%201D%20heat%20equation%20models%20thermal%20diffusion%3A%0A%0A%20%20%20%20%24%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20t%7D%20%3D%20%5Calpha%20%5Cfrac%7B%5Cpartial%5E2%20u%7D%7B%5Cpartial%20x%5E2%7D%24%24%0A%0A%20%20%20%20**Notation%3A**%0A%20%20%20%20-%20%24u(x%2Ct)%24%20%3D%20temperature%20at%20position%20%24x%24%20and%20time%20%24t%24%0A%20%20%20%20-%20%24%5Calpha%24%20%3D%20thermal%20diffusivity%20(controls%20diffusion%20rate%2C%20units%3A%20m%C2%B2%2Fs)%0A%0A%20%20%20%20**Physical%20Interpretation%3A**%20Heat%20flows%20from%20hot%20regions%20to%20cold%20regions%2C%20with%20rate%20proportional%20to%20the%20second%20spatial%20derivative%20(curvature).%20High%20curvature%20means%20rapid%20temperature%20change.%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20Problem%20Setup%0A%0A%20%20%20%20**Domain%3A**%20%24x%20%5Cin%20%5B0%2C%201%5D%24%2C%20%24t%20%5Cin%20%5B0%2C%20T%5D%24%0A%0A%20%20%20%20**Initial%20Condition%20(IC)%3A**%0A%0A%20%20%20%20%24%24u(x%2C%200)%20%3D%20%5Csin(%5Cpi%20x)%24%24%0A%0A%20%20%20%20Initial%20temperature%20distribution%20is%20a%20half%20sine%20wave%E2%80%94hot%20in%20the%20middle%2C%20cool%20at%20edges.%0A%0A%20%20%20%20**Boundary%20Conditions%20(BC)%3A**%0A%0A%20%20%20%20%24%24u(0%2C%20t)%20%3D%200%2C%20%5Cquad%20u(1%2C%20t)%20%3D%200%24%24%0A%0A%20%20%20%20Both%20endpoints%20are%20held%20at%20zero%20temperature%20(Dirichlet%20boundary%20conditions).%0A%0A%20%20%20%20**Analytical%20Solution%3A**%20For%20this%20specific%20problem%2C%20the%20exact%20solution%20is%20known%3A%0A%0A%20%20%20%20%24%24u(x%2Ct)%20%3D%20%5Csin(%5Cpi%20x)%20e%5E%7B-%5Cpi%5E2%20%5Calpha%20t%7D%24%24%0A%0A%20%20%20%20This%20allows%20us%20to%20validate%20PINN%20accuracy%20against%20ground%20truth%E2%80%94the%20spatial%20profile%20decays%20exponentially%20in%20time.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20torch%0A%20%20%20%20import%20torch.nn%20as%20nn%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20from%20mpl_toolkits.mplot3d%20import%20Axes3D%0A%20%20%20%20from%20matplotlib%20import%20cm%0A%0A%20%20%20%20return%20cm%2C%20mo%2C%20nn%2C%20np%2C%20plt%2C%20torch%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%20%20%20%20%23%23%201.%20The%20PINN%20Formulation%0A%0A%20%20%20%20%23%23%23%20Core%20Idea%0A%0A%20%20%20%20Approximate%20%24u(x%2Ct)%24%20with%20neural%20network%20%24u_%5Cphi(x%2Ct)%24%20by%20minimizing%3A%0A%0A%20%20%20%20%24%24%5Cmathcal%7BL%7D_%7B%5Ctext%7Btotal%7D%7D%20%3D%20w_%7B%5Ctext%7BPDE%7D%7D%20%5Cmathcal%7BL%7D_%7B%5Ctext%7BPDE%7D%7D%20%2B%20w_%7B%5Ctext%7BIC%7D%7D%20%5Cmathcal%7BL%7D_%7B%5Ctext%7BIC%7D%7D%20%2B%20w_%7B%5Ctext%7BBC%7D%7D%20%5Cmathcal%7BL%7D_%7B%5Ctext%7BBC%7D%7D%24%24%0A%0A%20%20%20%20where%20derivatives%20are%20computed%20via%20**automatic%20differentiation**.%0A%0A%20%20%20%20%23%23%23%201.1%20Physics%20Residual%0A%0A%20%20%20%20The%20governing%20equation%20enforces%20energy%20conservation%20at%20**collocation%20points**%20%24%5C%7B(x_i%2C%20t_i)%5C%7D%24%3A%0A%0A%20%20%20%20%24%24%5Cmathcal%7BR%7D_%7B%5Ctext%7BPDE%7D%7D(x%2C%20t)%20%3D%20%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20t%7D%20-%20%5Calpha%20%5Cfrac%7B%5Cpartial%5E2%20u%7D%7B%5Cpartial%20x%5E2%7D%20%3D%200%24%24%0A%0A%20%20%20%20**Physics%20Loss%3A**%0A%0A%20%20%20%20%24%24%5Cmathcal%7BL%7D_%7B%5Ctext%7BPDE%7D%7D%20%3D%20%5Cfrac%7B1%7D%7BN_c%7D%5Csum_%7Bi%3D1%7D%5E%7BN_c%7D%20%5Cleft%5B%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20t%7D(x_i%2C%20t_i)%20-%20%5Calpha%20%5Cfrac%7B%5Cpartial%5E2%20u%7D%7B%5Cpartial%20x%5E2%7D(x_i%2C%20t_i)%5Cright%5D%5E2%24%24%0A%0A%20%20%20%20%23%23%23%201.2%20Initial%20Condition%0A%0A%20%20%20%20Temperature%20distribution%20at%20%24t%3D0%24%3A%0A%0A%20%20%20%20%24%24%5Cmathcal%7BL%7D_%7B%5Ctext%7BIC%7D%7D%20%3D%20%5Cfrac%7B1%7D%7BN_%7B%5Ctext%7BIC%7D%7D%7D%5Csum_%7Bi%3D1%7D%5E%7BN_%7B%5Ctext%7BIC%7D%7D%7D%20%7Cu(x_i%2C%200)%20-%20%5Csin(%5Cpi%20x_i)%7C%5E2%24%24%0A%0A%20%20%20%20%23%23%23%201.3%20Boundary%20Conditions%0A%0A%20%20%20%20Fixed%20temperature%20at%20boundaries%20(Dirichlet%20BCs)%3A%0A%0A%20%20%20%20%24%24%5Cmathcal%7BL%7D_%7B%5Ctext%7BBC%7D%7D%20%3D%20%5Cfrac%7B1%7D%7BN_%7B%5Ctext%7BBC%7D%7D%7D%5Csum_%7Bi%3D1%7D%5E%7BN_%7B%5Ctext%7BBC%7D%7D%7D%20%5Cleft%5B%7Cu(0%2C%20t_i)%7C%5E2%20%2B%20%7Cu(1%2C%20t_i)%7C%5E2%5Cright%5D%24%24%0A%0A%20%20%20%20%23%23%23%20Why%20Multiple%20Loss%20Terms%3F%0A%0A%20%20%20%20-%20**PDE%20loss**%3A%20Ensures%20physics%20is%20satisfied%20throughout%20the%20domain%0A%20%20%20%20-%20**IC%20loss**%3A%20Matches%20initial%20temperature%20profile%0A%20%20%20%20-%20**BC%20loss**%3A%20Enforces%20boundary%20temperature%20constraints%0A%20%20%20%20-%20**Weights**%20%24w_%7B%5Ctext%7BPDE%7D%7D%2C%20w_%7B%5Ctext%7BIC%7D%7D%2C%20w_%7B%5Ctext%7BBC%7D%7D%24%3A%20Balance%20competing%20objectives%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20u_initial(x)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Initial%20condition%3A%20u(x%2C%200)%20%3D%20sin(pi*x)%22%22%22%0A%20%20%20%20%20%20%20%20return%20np.sin(np.pi%20*%20x)%0A%0A%20%20%20%20def%20u_analytical(x%2C%20t%2C%20alpha)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Analytical%20solution%3A%20u(x%2Ct)%20%3D%20sin(pi*x)%20*%20exp(-pi%5E2%20*%20alpha%20*%20t)%22%22%22%0A%20%20%20%20%20%20%20%20return%20np.sin(np.pi%20*%20x)%20*%20np.exp(-np.pi**2%20*%20alpha%20*%20t)%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(rf%22%22%22%0A%20%20%20%20%23%23%23%202.%20Neural%20Network%20Architecture%0A%0A%20%20%20%20A%20configurable%20feedforward%20network%20(tunable%20hidden%20layers%20and%20width%2C%20tanh%20activations)%20maps%20%24(x%2C%20t)%24%20to%20temperature%20%24u(x%2Ct)%24.%0A%0A%20%20%20%20**Input%20dimension%3A**%202%20(position%20%24x%24%20and%20time%20%24t%24)%0A%0A%20%20%20%20**Output%20dimension%3A**%201%20(temperature%20%24u%24)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(nn%2C%20torch)%3A%0A%20%20%20%20class%20PINN(nn.Module)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Physics-Informed%20Neural%20Network%20for%201D%20Heat%20Equation%0A%0A%20%20%20%20%20%20%20%20Architecture%3A%0A%20%20%20%20%20%20%20%20-%20Input%3A%20(x%2C%20t)%20%E2%88%88%20R%C2%B2%0A%20%20%20%20%20%20%20%20-%20Configurable%20hidden%20layers%20with%20adjustable%20width%0A%20%20%20%20%20%20%20%20-%20Tanh%20activation%20functions%0A%20%20%20%20%20%20%20%20-%20Output%3A%20u(x%2Ct)%20%E2%88%88%20R%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20width%3D32%2C%20num_layers%3D3)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20super(PINN%2C%20self).__init__()%0A%20%20%20%20%20%20%20%20%20%20%20%20layers%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20layers.append(nn.Linear(2%2C%20width))%20%20%23%202%20inputs%3A%20x%20and%20t%0A%20%20%20%20%20%20%20%20%20%20%20%20layers.append(nn.Tanh())%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20_%20in%20range(num_layers%20-%201)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20layers.append(nn.Linear(width%2C%20width))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20layers.append(nn.Tanh())%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20layers.append(nn.Linear(width%2C%201))%20%20%23%201%20output%3A%20u%0A%20%20%20%20%20%20%20%20%20%20%20%20self.net%20%3D%20nn.Sequential(*layers)%0A%0A%20%20%20%20%20%20%20%20def%20forward(self%2C%20x%2C%20t)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20inputs%20%3D%20torch.cat(%5Bx%2C%20t%5D%2C%20dim%3D1)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self.net(inputs)%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%202.2%20PDE%20Residual%20Computation%20via%20Automatic%20Differentiation%0A%0A%20%20%20%20PyTorch's%20%60torch.autograd.grad%60%20computes%20derivatives%20of%20the%20network%20output%20with%20respect%20to%20inputs.%0A%0A%20%20%20%20**Key%20steps%3A**%0A%0A%20%20%20%201.%20**First-order%20derivatives**%3A%20Compute%20%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20x%7D%24%20and%20%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20t%7D%24%20using%20%60torch.autograd.grad%60%20with%20%60create_graph%3DTrue%60%0A%20%20%20%202.%20**Second-order%20derivative**%3A%20Compute%20%24%5Cfrac%7B%5Cpartial%5E2%20u%7D%7B%5Cpartial%20x%5E2%7D%24%20by%20differentiating%20%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20x%7D%24%20again%0A%20%20%20%203.%20**Residual**%3A%20Combine%20as%20%24%5Cmathcal%7BR%7D%20%3D%20u_t%20-%20%5Calpha%20u_%7Bxx%7D%24%0A%0A%20%20%20%20**Why%20%60create_graph%3DTrue%60%3F**%20Enables%20higher-order%20derivatives%20by%20keeping%20the%20computational%20graph%20for%20backpropagation%20through%20the%20gradient%20computation%20itself.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(torch)%3A%0A%20%20%20%20def%20pde_residual(pinn_model%2C%20x%2C%20t%2C%20alpha)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Compute%20the%20PDE%20residual%20for%20the%20heat%20equation%0A%0A%20%20%20%20%20%20%20%20Residual%20%3D%20u_t%20-%20alpha%20*%20u_xx%0A%0A%20%20%20%20%20%20%20%20Uses%20automatic%20differentiation%20to%20compute%3A%0A%20%20%20%20%20%20%20%20-%20u_t%3A%20first%20derivative%20w.r.t.%20time%0A%20%20%20%20%20%20%20%20-%20u_x%3A%20first%20derivative%20w.r.t.%20space%0A%20%20%20%20%20%20%20%20-%20u_xx%3A%20second%20derivative%20w.r.t.%20space%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20%23%20Predict%20the%20solution%20u(x%2C%20t)%0A%20%20%20%20%20%20%20%20u%20%3D%20pinn_model(x%2C%20t)%0A%0A%20%20%20%20%20%20%20%20%23%20Compute%20partial%20derivatives%20using%20autograd%0A%20%20%20%20%20%20%20%20%23%20First%20derivatives%0A%20%20%20%20%20%20%20%20u_x%20%3D%20torch.autograd.grad(%0A%20%20%20%20%20%20%20%20%20%20%20%20u%2C%20x%2C%20torch.ones_like(u)%2C%20create_graph%3DTrue%2C%20retain_graph%3DTrue%0A%20%20%20%20%20%20%20%20)%5B0%5D%0A%20%20%20%20%20%20%20%20u_t%20%3D%20torch.autograd.grad(%0A%20%20%20%20%20%20%20%20%20%20%20%20u%2C%20t%2C%20torch.ones_like(u)%2C%20create_graph%3DTrue%2C%20retain_graph%3DTrue%0A%20%20%20%20%20%20%20%20)%5B0%5D%0A%0A%20%20%20%20%20%20%20%20%23%20Second%20spatial%20derivative%0A%20%20%20%20%20%20%20%20u_xx%20%3D%20torch.autograd.grad(%0A%20%20%20%20%20%20%20%20%20%20%20%20u_x%2C%20x%2C%20torch.ones_like(u_x)%2C%20create_graph%3DTrue%2C%20retain_graph%3DTrue%0A%20%20%20%20%20%20%20%20)%5B0%5D%0A%0A%20%20%20%20%20%20%20%20%23%20Calculate%20the%20PDE%20residual%3A%20u_t%20-%20alpha%20*%20u_xx%0A%20%20%20%20%20%20%20%20pde_res%20%3D%20u_t%20-%20alpha%20*%20u_xx%0A%20%20%20%20%20%20%20%20return%20pde_res%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%202.3%20Training%20Loop%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo%2C%20np)%3A%0A%20%20%20%20%40mo.persistent_cache%0A%20%20%20%20def%20train_model(%0A%20%20%20%20%20%20%20%20x_min%2C%0A%20%20%20%20%20%20%20%20x_max%2C%0A%20%20%20%20%20%20%20%20t_min%2C%0A%20%20%20%20%20%20%20%20t_max%2C%0A%20%20%20%20%20%20%20%20alpha%2C%0A%20%20%20%20%20%20%20%20n_collocation%2C%0A%20%20%20%20%20%20%20%20n_ic%2C%0A%20%20%20%20%20%20%20%20n_bc%2C%0A%20%20%20%20%20%20%20%20epochs%2C%0A%20%20%20%20%20%20%20%20lr%2C%0A%20%20%20%20%20%20%20%20pde_weight%2C%0A%20%20%20%20%20%20%20%20ic_weight%2C%0A%20%20%20%20%20%20%20%20bc_weight%2C%0A%20%20%20%20%20%20%20%20hidden_width%2C%0A%20%20%20%20%20%20%20%20num_layers%2C%0A%20%20%20%20%20%20%20%20print_every%2C%0A%20%20%20%20%20%20%20%20device_type%2C%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Train%20PINN%20for%201D%20heat%20equation%0A%0A%20%20%20%20%20%20%20%20All%20UI%20parameters%20are%20function%20arguments%20for%20persistent%20caching.%0A%20%20%20%20%20%20%20%20Returns%20dict%20with%20model%2C%20training%20history%2C%20and%20test%20predictions.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20import%20torch%0A%20%20%20%20%20%20%20%20import%20torch.nn%20as%20nn%0A%0A%20%20%20%20%20%20%20%20%23%20Import%20network%20and%20residual%20from%20outer%20scope%0A%20%20%20%20%20%20%20%20from%20__main__%20import%20PINN%2C%20pde_residual%2C%20u_initial%0A%0A%20%20%20%20%20%20%20%20device%20%3D%20torch.device(device_type)%0A%0A%20%20%20%20%20%20%20%20%23%20Generate%20collocation%20points%20(for%20PDE%20residual)%0A%20%20%20%20%20%20%20%20x_collocation%20%3D%20torch.rand(n_collocation%2C%201%2C%20device%3Ddevice)%20*%20(x_max%20-%20x_min)%20%2B%20x_min%0A%20%20%20%20%20%20%20%20t_collocation%20%3D%20torch.rand(n_collocation%2C%201%2C%20device%3Ddevice)%20*%20(t_max%20-%20t_min)%20%2B%20t_min%0A%20%20%20%20%20%20%20%20collocation_points%20%3D%20torch.cat(%5Bx_collocation%2C%20t_collocation%5D%2C%20dim%3D1)%0A%20%20%20%20%20%20%20%20collocation_points.requires_grad%20%3D%20True%0A%0A%20%20%20%20%20%20%20%20%23%20Generate%20initial%20condition%20points%20(IC)%0A%20%20%20%20%20%20%20%20x_ic%20%3D%20torch.rand(n_ic%2C%201%2C%20device%3Ddevice)%20*%20(x_max%20-%20x_min)%20%2B%20x_min%0A%20%20%20%20%20%20%20%20t_ic%20%3D%20torch.zeros(n_ic%2C%201%2C%20device%3Ddevice)%0A%20%20%20%20%20%20%20%20ic_points%20%3D%20torch.cat(%5Bx_ic%2C%20t_ic%5D%2C%20dim%3D1)%0A%20%20%20%20%20%20%20%20u_ic%20%3D%20torch.tensor(u_initial(x_ic.cpu().detach().numpy())%2C%20dtype%3Dtorch.float32%2C%20device%3Ddevice)%0A%0A%20%20%20%20%20%20%20%20%23%20Generate%20boundary%20condition%20points%20(BC)%0A%20%20%20%20%20%20%20%20t_bc%20%3D%20torch.rand(n_bc%2C%201%2C%20device%3Ddevice)%20*%20(t_max%20-%20t_min)%20%2B%20t_min%0A%20%20%20%20%20%20%20%20x_bc_left%20%3D%20torch.full((n_bc%2C%201)%2C%20x_min%2C%20device%3Ddevice)%0A%20%20%20%20%20%20%20%20x_bc_right%20%3D%20torch.full((n_bc%2C%201)%2C%20x_max%2C%20device%3Ddevice)%0A%20%20%20%20%20%20%20%20bc_points_left%20%3D%20torch.cat(%5Bx_bc_left%2C%20t_bc%5D%2C%20dim%3D1)%0A%20%20%20%20%20%20%20%20bc_points_right%20%3D%20torch.cat(%5Bx_bc_right%2C%20t_bc%5D%2C%20dim%3D1)%0A%0A%20%20%20%20%20%20%20%20%23%20Initialize%20model%0A%20%20%20%20%20%20%20%20pinn%20%3D%20PINN(width%3Dhidden_width%2C%20num_layers%3Dnum_layers).to(device)%0A%20%20%20%20%20%20%20%20optimizer%20%3D%20torch.optim.Adam(pinn.parameters()%2C%20lr%3Dlr)%0A%20%20%20%20%20%20%20%20loss_function%20%3D%20nn.MSELoss()%0A%0A%20%20%20%20%20%20%20%20%23%20Training%20loop%0A%20%20%20%20%20%20%20%20losses%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20'total'%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'pde'%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'ic'%3A%20%5B%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'bc'%3A%20%5B%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20epoch%20in%20range(1%2C%20epochs%20%2B%201)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20optimizer.zero_grad()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20PDE%20Loss%0A%20%20%20%20%20%20%20%20%20%20%20%20pde_res%20%3D%20pde_residual(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pinn%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collocation_points%5B%3A%2C%200%3A1%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collocation_points%5B%3A%2C%201%3A2%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20pde_loss%20%3D%20loss_function(pde_res%2C%20torch.zeros_like(pde_res))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20IC%20Loss%0A%20%20%20%20%20%20%20%20%20%20%20%20u_ic_pred%20%3D%20pinn(ic_points%5B%3A%2C%200%3A1%5D%2C%20ic_points%5B%3A%2C%201%3A2%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20ic_loss%20%3D%20loss_function(u_ic_pred%2C%20u_ic)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20BC%20Loss%0A%20%20%20%20%20%20%20%20%20%20%20%20u_bc_pred_left%20%3D%20pinn(bc_points_left%5B%3A%2C%200%3A1%5D%2C%20bc_points_left%5B%3A%2C%201%3A2%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20u_bc_pred_right%20%3D%20pinn(bc_points_right%5B%3A%2C%200%3A1%5D%2C%20bc_points_right%5B%3A%2C%201%3A2%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20bc_loss%20%3D%20loss_function(u_bc_pred_left%2C%20torch.zeros_like(u_bc_pred_left))%20%2B%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loss_function(u_bc_pred_right%2C%20torch.zeros_like(u_bc_pred_right))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Total%20loss%20with%20weights%0A%20%20%20%20%20%20%20%20%20%20%20%20loss%20%3D%20pde_weight%20*%20pde_loss%20%2B%20ic_weight%20*%20ic_loss%20%2B%20bc_weight%20*%20bc_loss%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20loss.backward()%0A%20%20%20%20%20%20%20%20%20%20%20%20optimizer.step()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Record%20losses%0A%20%20%20%20%20%20%20%20%20%20%20%20losses%5B'total'%5D.append(loss.item())%0A%20%20%20%20%20%20%20%20%20%20%20%20losses%5B'pde'%5D.append(pde_loss.item())%0A%20%20%20%20%20%20%20%20%20%20%20%20losses%5B'ic'%5D.append(ic_loss.item())%0A%20%20%20%20%20%20%20%20%20%20%20%20losses%5B'bc'%5D.append(bc_loss.item())%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20epoch%20%25%20print_every%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Epoch%20%5B%7Bepoch%7D%2F%7Bepochs%7D%5D%2C%20Total%20Loss%3A%20%7Bloss.item()%3A.6f%7D%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22PDE%3A%20%7Bpde_loss.item()%3A.6f%7D%2C%20IC%3A%20%7Bic_loss.item()%3A.6f%7D%2C%20BC%3A%20%7Bbc_loss.item()%3A.6f%7D%22)%0A%0A%20%20%20%20%20%20%20%20%23%20Generate%20test%20predictions%0A%20%20%20%20%20%20%20%20n_points%20%3D%20100%0A%20%20%20%20%20%20%20%20x_test%20%3D%20np.linspace(x_min%2C%20x_max%2C%20n_points)%0A%20%20%20%20%20%20%20%20t_test%20%3D%20np.linspace(t_min%2C%20t_max%2C%20n_points)%0A%20%20%20%20%20%20%20%20X_test%2C%20T_test%20%3D%20np.meshgrid(x_test%2C%20t_test)%0A%20%20%20%20%20%20%20%20x_test_flat%20%3D%20torch.tensor(X_test.flatten()%2C%20dtype%3Dtorch.float32%2C%20device%3Ddevice).view(-1%2C%201)%0A%20%20%20%20%20%20%20%20t_test_flat%20%3D%20torch.tensor(T_test.flatten()%2C%20dtype%3Dtorch.float32%2C%20device%3Ddevice).view(-1%2C%201)%0A%0A%20%20%20%20%20%20%20%20with%20torch.no_grad()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20u_pred_test%20%3D%20pinn(x_test_flat%2C%20t_test_flat).cpu().numpy().reshape(n_points%2C%20n_points)%0A%0A%20%20%20%20%20%20%20%20%23%20Compute%20analytical%20solution%0A%20%20%20%20%20%20%20%20u_analytical_test%20%3D%20np.sin(np.pi%20*%20X_test)%20*%20np.exp(-np.pi**2%20*%20alpha%20*%20T_test)%0A%0A%20%20%20%20%20%20%20%20%23%20Convert%20collocation%20points%20to%20numpy%0A%20%20%20%20%20%20%20%20collocation_np%20%3D%20collocation_points.detach().cpu().numpy()%0A%0A%20%20%20%20%20%20%20%20%23%20Compute%20PDE%20residuals%20at%20collocation%20points%0A%20%20%20%20%20%20%20%20%23%20Note%3A%20pde_residual%20requires%20gradients%2C%20so%20we%20can't%20use%20torch.no_grad()%0A%20%20%20%20%20%20%20%20pde_res_final%20%3D%20pde_residual(%0A%20%20%20%20%20%20%20%20%20%20%20%20pinn%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20collocation_points%5B%3A%2C%200%3A1%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20collocation_points%5B%3A%2C%201%3A2%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%0A%20%20%20%20%20%20%20%20).detach().cpu().numpy()%0A%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20'model'%3A%20pinn%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'losses'%3A%20losses%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'x_test'%3A%20x_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20't_test'%3A%20t_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'X_test'%3A%20X_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'T_test'%3A%20T_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'u_pred'%3A%20u_pred_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'u_analytical'%3A%20u_analytical_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'collocation_points'%3A%20collocation_np%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'pde_residuals'%3A%20pde_res_final%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20return%20(train_model%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%20%20%20%20%3Ca%20id%3D%22control-panel%22%3E%3C%2Fa%3E%0A%20%20%20%20%23%23%203.%20Interactive%20Parameters%20%26%20Training%0A%0A%20%20%20%20-%20**Physical%20parameters**%3A%20Thermal%20diffusivity%2C%20domain%20size%0A%20%20%20%20-%20**Training%20parameters**%3A%20Collocation%20points%2C%20epochs%2C%20learning%20rate%0A%20%20%20%20-%20**Loss%20weights**%3A%20Balance%20between%20PDE%2C%20IC%2C%20and%20BC%20enforcement%0A%20%20%20%20-%20**Network%20architecture**%3A%20Hidden%20layer%20width%0A%20%20%20%20-%20**Visualization**%3A%20GIF%20generation%20options%0A%0A%20%20%20%20**Tuning%20tips%3A**%0A%20%20%20%20-%20Keep%20physical%20parameters%20fixed%20unless%20the%20exercise%20explicitly%20asks%20you%20to%20change%20them.%0A%20%20%20%20-%20Increase%20collocation%20points%20to%20improve%20PDE%20coverage%3B%20this%20usually%20improves%20accuracy%20but%20increases%20runtime.%0A%20%20%20%20-%20Increase%20epochs%20while%20losses%20are%20still%20decreasing%3B%20stop%20when%20improvement%20plateaus.%0A%20%20%20%20-%20Lower%20learning%20rate%20if%20training%20oscillates%2Fdiverges%3B%20raise%20it%20slightly%20if%20convergence%20is%20too%20slow.%0A%20%20%20%20-%20Rebalance%20loss%20weights%20if%20IC%2FBC%20errors%20stay%20high%20while%20PDE%20loss%20decreases%20(or%20vice%20versa).%0A%20%20%20%20-%20Increase%20network%20width%2Fdepth%20for%20sharper%20solution%20features%3B%20larger%20models%20are%20slower%20and%20harder%20to%20train.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo%2C%20torch)%3A%0A%20%20%20%20%23%20Physical%20parameters%0A%20%20%20%20alpha_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%200.001%2C%200.1%2C%20value%3D0.01%2C%20step%3D0.001%2C%20label%3D%22Thermal%20diffusivity%20%CE%B1%22%0A%20%20%20%20)%0A%20%20%20%20x_max_slider%20%3D%20mo.ui.slider(0.5%2C%202.0%2C%20value%3D1.0%2C%20step%3D0.1%2C%20label%3D%22Domain%20length%20L%22)%0A%20%20%20%20t_max_slider%20%3D%20mo.ui.slider(0.5%2C%202.0%2C%20value%3D1.0%2C%20step%3D0.1%2C%20label%3D%22Time%20horizon%20T%22)%0A%0A%20%20%20%20%23%20Training%20parameters%0A%20%20%20%20n_collocation_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%201000%2C%2010000%2C%20value%3D5000%2C%20step%3D500%2C%20label%3D%22Collocation%20points%22%0A%20%20%20%20)%0A%20%20%20%20n_ic_slider%20%3D%20mo.ui.slider(50%2C%20300%2C%20value%3D100%2C%20step%3D10%2C%20label%3D%22IC%20points%22)%0A%20%20%20%20n_bc_slider%20%3D%20mo.ui.slider(50%2C%20300%2C%20value%3D100%2C%20step%3D10%2C%20label%3D%22BC%20points%22)%0A%20%20%20%20epochs_dropdown%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%225k%22%3A%205000%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2210k%22%3A%2010000%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2220k%22%3A%2020000%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2240k%22%3A%2040000%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2260k%22%3A%2060000%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20value%3D%2240k%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Epochs%22%2C%0A%20%20%20%20)%0A%20%20%20%20lr_dropdown%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20%7B%221e-4%22%3A%201e-4%2C%20%225e-4%22%3A%205e-4%2C%20%221e-3%22%3A%201e-3%2C%20%222e-3%22%3A%202e-3%7D%2C%0A%20%20%20%20%20%20%20%20value%3D%221e-3%22%2C%0A%20%20%20%20%20%20%20%20label%3D%22Learning%20rate%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Loss%20weights%0A%20%20%20%20pde_weight_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%200.1%2C%2010.0%2C%20value%3D1.0%2C%20step%3D0.1%2C%20label%3D%22PDE%20loss%20weight%22%0A%20%20%20%20)%0A%20%20%20%20ic_weight_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%200.1%2C%2020.0%2C%20value%3D10.0%2C%20step%3D0.5%2C%20label%3D%22IC%20loss%20weight%22%0A%20%20%20%20)%0A%20%20%20%20bc_weight_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%200.1%2C%2020.0%2C%20value%3D10.0%2C%20step%3D0.5%2C%20label%3D%22BC%20loss%20weight%22%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Network%20architecture%0A%20%20%20%20hidden_width_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%2016%2C%2064%2C%20value%3D32%2C%20step%3D8%2C%20label%3D%22Hidden%20layer%20width%22%0A%20%20%20%20)%0A%20%20%20%20num_layers_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%201%2C%205%2C%20value%3D3%2C%20step%3D1%2C%20label%3D%22Number%20of%20hidden%20layers%22%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Visualization%0A%20%20%20%20print_every_slider%20%3D%20mo.ui.slider(%0A%20%20%20%20%20%20%20%20500%2C%205000%2C%20value%3D2000%2C%20step%3D500%2C%20label%3D%22Print%20interval%20(epochs)%22%0A%20%20%20%20)%0A%0A%0A%20%20%20%20device%20%3D%20torch.device(%22cuda%22%20if%20torch.cuda.is_available()%20else%20%22cpu%22)%0A%0A%20%20%20%20control_panel%20%3D%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Physical%20Parameters%22)%2C%0A%20%20%20%20%20%20%20%20alpha_slider%2C%0A%20%20%20%20%20%20%20%20x_max_slider%2C%0A%20%20%20%20%20%20%20%20t_max_slider%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Domain%20Sampling%22)%2C%0A%20%20%20%20%20%20%20%20n_collocation_slider%2C%0A%20%20%20%20%20%20%20%20n_ic_slider%2C%0A%20%20%20%20%20%20%20%20n_bc_slider%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Training%20Configuration%22)%2C%0A%20%20%20%20%20%20%20%20epochs_dropdown%2C%0A%20%20%20%20%20%20%20%20lr_dropdown%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Network%20Architecture%22)%2C%0A%20%20%20%20%20%20%20%20hidden_width_slider%2C%0A%20%20%20%20%20%20%20%20num_layers_slider%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Loss%20Weights%22)%2C%0A%20%20%20%20%20%20%20%20pde_weight_slider%2C%0A%20%20%20%20%20%20%20%20ic_weight_slider%2C%0A%20%20%20%20%20%20%20%20bc_weight_slider%2C%0A%20%20%20%20%20%20%20%20mo.md(%22%23%23%23%23%20Visualization%22)%2C%0A%20%20%20%20%20%20%20%20print_every_slider%2C%0A%20%20%20%20%20%20%20%20mo.md(%22---%22)%2C%0A%20%20%20%20%20%20%20%20mo.md(f%22**Device%3A**%20%60%7Bdevice%7D%60%22)%2C%0A%20%20%20%20%5D)%0A%0A%20%20%20%20train_button%20%3D%20mo.ui.run_button(label%3D%22%E2%96%B6%20Train%20PINN%22)%0A%0A%20%20%20%20mo.vstack(%5Btrain_button%2C%20control_panel%5D)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20alpha_slider%2C%0A%20%20%20%20%20%20%20%20bc_weight_slider%2C%0A%20%20%20%20%20%20%20%20device%2C%0A%20%20%20%20%20%20%20%20epochs_dropdown%2C%0A%20%20%20%20%20%20%20%20hidden_width_slider%2C%0A%20%20%20%20%20%20%20%20ic_weight_slider%2C%0A%20%20%20%20%20%20%20%20lr_dropdown%2C%0A%20%20%20%20%20%20%20%20n_bc_slider%2C%0A%20%20%20%20%20%20%20%20n_collocation_slider%2C%0A%20%20%20%20%20%20%20%20n_ic_slider%2C%0A%20%20%20%20%20%20%20%20num_layers_slider%2C%0A%20%20%20%20%20%20%20%20pde_weight_slider%2C%0A%20%20%20%20%20%20%20%20print_every_slider%2C%0A%20%20%20%20%20%20%20%20t_max_slider%2C%0A%20%20%20%20%20%20%20%20train_button%2C%0A%20%20%20%20%20%20%20%20x_max_slider%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20alpha_slider%2C%0A%20%20%20%20bc_weight_slider%2C%0A%20%20%20%20device%2C%0A%20%20%20%20epochs_dropdown%2C%0A%20%20%20%20hidden_width_slider%2C%0A%20%20%20%20ic_weight_slider%2C%0A%20%20%20%20lr_dropdown%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_bc_slider%2C%0A%20%20%20%20n_collocation_slider%2C%0A%20%20%20%20n_ic_slider%2C%0A%20%20%20%20num_layers_slider%2C%0A%20%20%20%20pde_weight_slider%2C%0A%20%20%20%20print_every_slider%2C%0A%20%20%20%20t_max_slider%2C%0A%20%20%20%20train_button%2C%0A%20%20%20%20train_model%2C%0A%20%20%20%20x_max_slider%2C%0A)%3A%0A%20%20%20%20mo.stop(not%20train_button.value%2C%20mo.md(%22_Click%20**%E2%96%B6%20Train%20PINN**%20to%20begin%20training_%22))%0A%0A%20%20%20%20results%20%3D%20train_model(%0A%20%20%20%20%20%20%20%20x_min%3D0.0%2C%0A%20%20%20%20%20%20%20%20x_max%3Dx_max_slider.value%2C%0A%20%20%20%20%20%20%20%20t_min%3D0.0%2C%0A%20%20%20%20%20%20%20%20t_max%3Dt_max_slider.value%2C%0A%20%20%20%20%20%20%20%20alpha%3Dalpha_slider.value%2C%0A%20%20%20%20%20%20%20%20n_collocation%3Dn_collocation_slider.value%2C%0A%20%20%20%20%20%20%20%20n_ic%3Dn_ic_slider.value%2C%0A%20%20%20%20%20%20%20%20n_bc%3Dn_bc_slider.value%2C%0A%20%20%20%20%20%20%20%20epochs%3Depochs_dropdown.value%2C%0A%20%20%20%20%20%20%20%20lr%3Dlr_dropdown.value%2C%0A%20%20%20%20%20%20%20%20pde_weight%3Dpde_weight_slider.value%2C%0A%20%20%20%20%20%20%20%20ic_weight%3Dic_weight_slider.value%2C%0A%20%20%20%20%20%20%20%20bc_weight%3Dbc_weight_slider.value%2C%0A%20%20%20%20%20%20%20%20hidden_width%3Dhidden_width_slider.value%2C%0A%20%20%20%20%20%20%20%20num_layers%3Dnum_layers_slider.value%2C%0A%20%20%20%20%20%20%20%20print_every%3Dprint_every_slider.value%2C%0A%20%20%20%20%20%20%20%20device_type%3Ddevice.type%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.md(f%22%E2%9C%85%20**Training%20complete!**%20Final%20total%20loss%3A%20%7Bresults%5B'losses'%5D%5B'total'%5D%5B-1%5D%3A.6e%7D%22)%0A%20%20%20%20return%20(results%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%20%20%20%20%23%23%204.%20Results%20Analysis%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.1%203D%20Surface%20Plot%3A%20PINN%20Solution%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(cm%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_3d%20%3D%20plt.figure(figsize%3D(12%2C%208))%0A%20%20%20%20ax_3d%20%3D%20fig_3d.add_subplot(111%2C%20projection%3D'3d')%0A%20%20%20%20surf%20%3D%20ax_3d.plot_surface(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'u_pred'%5D%2C%0A%20%20%20%20%20%20%20%20cmap%3Dcm.viridis%2C%0A%20%20%20%20%20%20%20%20linewidth%3D0%2C%0A%20%20%20%20%20%20%20%20antialiased%3DTrue%2C%0A%20%20%20%20%20%20%20%20alpha%3D0.9%0A%20%20%20%20)%0A%20%20%20%20ax_3d.set_title(%22PINN%20Solution%3A%20u(x%2C%20t)%22%2C%20fontsize%3D14%2C%20fontweight%3D'bold')%0A%20%20%20%20ax_3d.set_xlabel(%22Position%20x%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_3d.set_ylabel(%22Time%20t%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_3d.set_zlabel(%22Temperature%20u%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_3d.view_init(elev%3D25%2C%20azim%3D135)%0A%20%20%20%20fig_3d.colorbar(surf%2C%20ax%3Dax_3d%2C%20shrink%3D0.5%2C%20aspect%3D10)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_3d%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.2%20Comparison%20with%20Analytical%20Solution%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(cm%2C%20np%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_compare%20%3D%20plt.figure(figsize%3D(18%2C%205))%0A%0A%20%20%20%20%23%20PINN%20Solution%0A%20%20%20%20ax1%20%3D%20fig_compare.add_subplot(131%2C%20projection%3D'3d')%0A%20%20%20%20surf1%20%3D%20ax1.plot_surface(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'u_pred'%5D%2C%0A%20%20%20%20%20%20%20%20cmap%3Dcm.viridis%2C%0A%20%20%20%20%20%20%20%20linewidth%3D0%2C%0A%20%20%20%20%20%20%20%20antialiased%3DTrue%0A%20%20%20%20)%0A%20%20%20%20ax1.set_title(%22PINN%20Solution%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20ax1.set_xlabel(%22x%22)%0A%20%20%20%20ax1.set_ylabel(%22t%22)%0A%20%20%20%20ax1.set_zlabel(%22u%22)%0A%0A%20%20%20%20%23%20Analytical%20Solution%0A%20%20%20%20ax2%20%3D%20fig_compare.add_subplot(132%2C%20projection%3D'3d')%0A%20%20%20%20surf2%20%3D%20ax2.plot_surface(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'u_analytical'%5D%2C%0A%20%20%20%20%20%20%20%20cmap%3Dcm.viridis%2C%0A%20%20%20%20%20%20%20%20linewidth%3D0%2C%0A%20%20%20%20%20%20%20%20antialiased%3DTrue%0A%20%20%20%20)%0A%20%20%20%20ax2.set_title(%22Analytical%20Solution%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20ax2.set_xlabel(%22x%22)%0A%20%20%20%20ax2.set_ylabel(%22t%22)%0A%20%20%20%20ax2.set_zlabel(%22u%22)%0A%0A%20%20%20%20%23%20Error%0A%20%20%20%20error%20%3D%20np.abs(results%5B'u_pred'%5D%20-%20results%5B'u_analytical'%5D)%0A%20%20%20%20ax3%20%3D%20fig_compare.add_subplot(133%2C%20projection%3D'3d')%0A%20%20%20%20surf3%20%3D%20ax3.plot_surface(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20error%2C%0A%20%20%20%20%20%20%20%20cmap%3Dcm.plasma%2C%0A%20%20%20%20%20%20%20%20linewidth%3D0%2C%0A%20%20%20%20%20%20%20%20antialiased%3DTrue%0A%20%20%20%20)%0A%20%20%20%20ax3.set_title(%22Absolute%20Error%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20ax3.set_xlabel(%22x%22)%0A%20%20%20%20ax3.set_ylabel(%22t%22)%0A%20%20%20%20ax3.set_zlabel(%22%7Cerror%7C%22)%0A%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_compare%0A%20%20%20%20return%20(error%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.3%202D%20Heatmap%20Visualization%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(error%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_heatmap%2C%20axes%20%3D%20plt.subplots(1%2C%203%2C%20figsize%3D(18%2C%205))%0A%0A%20%20%20%20%23%20PINN%20Solution%0A%20%20%20%20im1%20%3D%20axes%5B0%5D.contourf(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'u_pred'%5D%2C%0A%20%20%20%20%20%20%20%20levels%3D30%2C%0A%20%20%20%20%20%20%20%20cmap%3D'viridis'%0A%20%20%20%20)%0A%20%20%20%20axes%5B0%5D.set_title(%22PINN%20Solution%20u(x%2Ct)%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20axes%5B0%5D.set_xlabel(%22Position%20x%22)%0A%20%20%20%20axes%5B0%5D.set_ylabel(%22Time%20t%22)%0A%20%20%20%20plt.colorbar(im1%2C%20ax%3Daxes%5B0%5D)%0A%0A%20%20%20%20%23%20Analytical%20Solution%0A%20%20%20%20im2%20%3D%20axes%5B1%5D.contourf(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'u_analytical'%5D%2C%0A%20%20%20%20%20%20%20%20levels%3D30%2C%0A%20%20%20%20%20%20%20%20cmap%3D'viridis'%0A%20%20%20%20)%0A%20%20%20%20axes%5B1%5D.set_title(%22Analytical%20Solution%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20axes%5B1%5D.set_xlabel(%22Position%20x%22)%0A%20%20%20%20axes%5B1%5D.set_ylabel(%22Time%20t%22)%0A%20%20%20%20plt.colorbar(im2%2C%20ax%3Daxes%5B1%5D)%0A%0A%20%20%20%20%23%20Error%0A%20%20%20%20im3%20%3D%20axes%5B2%5D.contourf(%0A%20%20%20%20%20%20%20%20results%5B'X_test'%5D%2C%0A%20%20%20%20%20%20%20%20results%5B'T_test'%5D%2C%0A%20%20%20%20%20%20%20%20error%2C%0A%20%20%20%20%20%20%20%20levels%3D30%2C%0A%20%20%20%20%20%20%20%20cmap%3D'plasma'%0A%20%20%20%20)%0A%20%20%20%20axes%5B2%5D.set_title(%22Absolute%20Error%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20axes%5B2%5D.set_xlabel(%22Position%20x%22)%0A%20%20%20%20axes%5B2%5D.set_ylabel(%22Time%20t%22)%0A%20%20%20%20plt.colorbar(im3%2C%20ax%3Daxes%5B2%5D)%0A%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_heatmap%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.4%20Temporal%20Slices%3A%20u(x)%20at%20Different%20Times%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(np%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_time_slices%2C%20ax_time%20%3D%20plt.subplots(figsize%3D(12%2C%206))%0A%0A%20%20%20%20%23%20Select%205%20time%20slices%0A%20%20%20%20t_slices%20%3D%20%5B0.1%2C%200.3%2C%200.5%2C%200.7%2C%200.9%5D%0A%20%20%20%20t_max_val%20%3D%20results%5B't_test'%5D.max()%0A%0A%20%20%20%20for%20t_val%20in%20t_slices%3A%0A%20%20%20%20%20%20%20%20if%20t_val%20%3C%3D%20t_max_val%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Find%20closest%20time%20index%0A%20%20%20%20%20%20%20%20%20%20%20%20t_idx%20%3D%20np.argmin(np.abs(results%5B't_test'%5D%20-%20t_val))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20PINN%20solution%0A%20%20%20%20%20%20%20%20%20%20%20%20ax_time.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5B'x_test'%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5B'u_pred'%5D%5Bt_idx%2C%20%3A%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Df't%3D%7Bt_val%3A.1f%7D%20(PINN)'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D2%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Analytical%20solution%0A%20%20%20%20%20%20%20%20%20%20%20%20ax_time.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5B'x_test'%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20results%5B'u_analytical'%5D%5Bt_idx%2C%20%3A%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'--'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20label%3Df't%3D%7Bt_val%3A.1f%7D%20(Analytical)'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha%3D0.7%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20ax_time.set_xlabel(%22Position%20x%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_time.set_ylabel(%22Temperature%20u%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_time.set_title(%22Temperature%20Distribution%20at%20Different%20Times%22%2C%20fontsize%3D14%2C%20fontweight%3D'bold')%0A%20%20%20%20ax_time.legend(ncol%3D2%2C%20fontsize%3D9)%0A%20%20%20%20ax_time.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_time_slices%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.5%20Spatial%20Slices%3A%20u(t)%20at%20Different%20Positions%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(np%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_space_slices%2C%20ax_space%20%3D%20plt.subplots(figsize%3D(12%2C%206))%0A%0A%20%20%20%20%23%20Select%205%20spatial%20positions%0A%20%20%20%20x_max_val%20%3D%20results%5B'x_test'%5D.max()%0A%20%20%20%20x_slices%20%3D%20%5B0.25%20*%20x_max_val%2C%200.5%20*%20x_max_val%2C%200.75%20*%20x_max_val%5D%0A%0A%20%20%20%20for%20x_val%20in%20x_slices%3A%0A%20%20%20%20%20%20%20%20%23%20Find%20closest%20position%20index%0A%20%20%20%20%20%20%20%20x_idx%20%3D%20np.argmin(np.abs(results%5B'x_test'%5D%20-%20x_val))%0A%0A%20%20%20%20%20%20%20%20%23%20PINN%20solution%0A%20%20%20%20%20%20%20%20ax_space.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20results%5B't_test'%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20results%5B'u_pred'%5D%5B%3A%2C%20x_idx%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20label%3Df'x%3D%7Bx_val%3A.2f%7D%20(PINN)'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20linewidth%3D2%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%23%20Analytical%20solution%0A%20%20%20%20%20%20%20%20ax_space.plot(%0A%20%20%20%20%20%20%20%20%20%20%20%20results%5B't_test'%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20results%5B'u_analytical'%5D%5B%3A%2C%20x_idx%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20'--'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20label%3Df'x%3D%7Bx_val%3A.2f%7D%20(Analytical)'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%3D0.7%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20ax_space.set_xlabel(%22Time%20t%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_space.set_ylabel(%22Temperature%20u%22%2C%20fontsize%3D12)%0A%20%20%20%20ax_space.set_title(%22Temperature%20Evolution%20at%20Different%20Positions%22%2C%20fontsize%3D14%2C%20fontweight%3D'bold')%0A%20%20%20%20ax_space.legend(ncol%3D2%2C%20fontsize%3D9)%0A%20%20%20%20ax_space.grid(True%2C%20alpha%3D0.3)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_space_slices%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.6%20Physics%20Residual%20Validation%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(np%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_residual%2C%20axes_res%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(16%2C%205))%0A%0A%20%20%20%20%23%20Scatter%20plot%20of%20residuals%0A%20%20%20%20residuals_flat%20%3D%20results%5B'pde_residuals'%5D.flatten()%0A%20%20%20%20x_col%20%3D%20results%5B'collocation_points'%5D%5B%3A%2C%200%5D%0A%20%20%20%20t_col%20%3D%20results%5B'collocation_points'%5D%5B%3A%2C%201%5D%0A%0A%20%20%20%20sc%20%3D%20axes_res%5B0%5D.scatter(%0A%20%20%20%20%20%20%20%20x_col%2C%0A%20%20%20%20%20%20%20%20t_col%2C%0A%20%20%20%20%20%20%20%20c%3Dnp.abs(residuals_flat)%2C%0A%20%20%20%20%20%20%20%20cmap%3D'plasma'%2C%0A%20%20%20%20%20%20%20%20s%3D1%2C%0A%20%20%20%20%20%20%20%20alpha%3D0.6%0A%20%20%20%20)%0A%20%20%20%20axes_res%5B0%5D.set_xlabel(%22Position%20x%22%2C%20fontsize%3D12)%0A%20%20%20%20axes_res%5B0%5D.set_ylabel(%22Time%20t%22%2C%20fontsize%3D12)%0A%20%20%20%20axes_res%5B0%5D.set_title(%22PDE%20Residual%20Magnitude%20%7CR(x%2Ct)%7C%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20plt.colorbar(sc%2C%20ax%3Daxes_res%5B0%5D)%0A%0A%20%20%20%20%23%20Histogram%20of%20residuals%0A%20%20%20%20axes_res%5B1%5D.hist(residuals_flat%2C%20bins%3D50%2C%20edgecolor%3D'black'%2C%20alpha%3D0.7)%0A%20%20%20%20axes_res%5B1%5D.axvline(0%2C%20color%3D'red'%2C%20linestyle%3D'--'%2C%20linewidth%3D2%2C%20label%3D'Zero%20residual')%0A%20%20%20%20axes_res%5B1%5D.set_xlabel(%22Residual%20value%22%2C%20fontsize%3D12)%0A%20%20%20%20axes_res%5B1%5D.set_ylabel(%22Frequency%22%2C%20fontsize%3D12)%0A%20%20%20%20axes_res%5B1%5D.set_title(%22Distribution%20of%20PDE%20Residuals%22%2C%20fontsize%3D12%2C%20fontweight%3D'bold')%0A%20%20%20%20axes_res%5B1%5D.legend()%0A%20%20%20%20axes_res%5B1%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20plt.tight_layout()%0A%0A%20%20%20%20residual_stats%20%3D%20f%22%22%22%0A%20%20%20%20**Residual%20Statistics%3A**%0A%20%20%20%20-%20Mean%3A%20%7Bnp.mean(residuals_flat)%3A.6e%7D%0A%20%20%20%20-%20Std%3A%20%7Bnp.std(residuals_flat)%3A.6e%7D%0A%20%20%20%20-%20Max%3A%20%7Bnp.max(np.abs(residuals_flat))%3A.6e%7D%0A%20%20%20%20-%20L2%20norm%3A%20%7Bnp.linalg.norm(residuals_flat)%3A.6e%7D%0A%20%20%20%20%22%22%22%0A%0A%20%20%20%20fig_residual%0A%20%20%20%20return%20residual_stats%2C%20residuals_flat%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo%2C%20residual_stats)%3A%0A%20%20%20%20mo.md(residual_stats)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.7%20Training%20Dynamics%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(np%2C%20plt%2C%20results)%3A%0A%20%20%20%20fig_training%2C%20axes_train%20%3D%20plt.subplots(2%2C%202%2C%20figsize%3D(16%2C%2010))%0A%0A%20%20%20%20epochs_array%20%3D%20np.arange(1%2C%20len(results%5B'losses'%5D%5B'total'%5D)%20%2B%201)%0A%0A%20%20%20%20%23%20Total%20loss%20(log%20scale)%0A%20%20%20%20axes_train%5B0%2C%200%5D.semilogy(epochs_array%2C%20results%5B'losses'%5D%5B'total'%5D%2C%20linewidth%3D2%2C%20color%3D'black')%0A%20%20%20%20axes_train%5B0%2C%200%5D.set_xlabel(%22Epoch%22)%0A%20%20%20%20axes_train%5B0%2C%200%5D.set_ylabel(%22Total%20Loss%20(log%20scale)%22)%0A%20%20%20%20axes_train%5B0%2C%200%5D.set_title(%22Total%20Loss%20Evolution%22%2C%20fontweight%3D'bold')%0A%20%20%20%20axes_train%5B0%2C%200%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20%23%20Individual%20losses%20(log%20scale)%0A%20%20%20%20axes_train%5B0%2C%201%5D.semilogy(epochs_array%2C%20results%5B'losses'%5D%5B'pde'%5D%2C%20label%3D'PDE'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B0%2C%201%5D.semilogy(epochs_array%2C%20results%5B'losses'%5D%5B'ic'%5D%2C%20label%3D'IC'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B0%2C%201%5D.semilogy(epochs_array%2C%20results%5B'losses'%5D%5B'bc'%5D%2C%20label%3D'BC'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B0%2C%201%5D.set_xlabel(%22Epoch%22)%0A%20%20%20%20axes_train%5B0%2C%201%5D.set_ylabel(%22Loss%20(log%20scale)%22)%0A%20%20%20%20axes_train%5B0%2C%201%5D.set_title(%22Loss%20Components%20(Log%20Scale)%22%2C%20fontweight%3D'bold')%0A%20%20%20%20axes_train%5B0%2C%201%5D.legend()%0A%20%20%20%20axes_train%5B0%2C%201%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20%23%20Total%20loss%20(linear%20scale)%0A%20%20%20%20axes_train%5B1%2C%200%5D.plot(epochs_array%2C%20results%5B'losses'%5D%5B'total'%5D%2C%20linewidth%3D2%2C%20color%3D'black')%0A%20%20%20%20axes_train%5B1%2C%200%5D.set_xlabel(%22Epoch%22)%0A%20%20%20%20axes_train%5B1%2C%200%5D.set_ylabel(%22Total%20Loss%22)%0A%20%20%20%20axes_train%5B1%2C%200%5D.set_title(%22Total%20Loss%20Evolution%20(Linear%20Scale)%22%2C%20fontweight%3D'bold')%0A%20%20%20%20axes_train%5B1%2C%200%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20%23%20Individual%20losses%20(linear%20scale)%0A%20%20%20%20axes_train%5B1%2C%201%5D.plot(epochs_array%2C%20results%5B'losses'%5D%5B'pde'%5D%2C%20label%3D'PDE'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B1%2C%201%5D.plot(epochs_array%2C%20results%5B'losses'%5D%5B'ic'%5D%2C%20label%3D'IC'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B1%2C%201%5D.plot(epochs_array%2C%20results%5B'losses'%5D%5B'bc'%5D%2C%20label%3D'BC'%2C%20alpha%3D0.8)%0A%20%20%20%20axes_train%5B1%2C%201%5D.set_xlabel(%22Epoch%22)%0A%20%20%20%20axes_train%5B1%2C%201%5D.set_ylabel(%22Loss%22)%0A%20%20%20%20axes_train%5B1%2C%201%5D.set_title(%22Loss%20Components%20(Linear%20Scale)%22%2C%20fontweight%3D'bold')%0A%20%20%20%20axes_train%5B1%2C%201%5D.legend()%0A%20%20%20%20axes_train%5B1%2C%201%5D.grid(True%2C%20alpha%3D0.3)%0A%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20fig_training%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%204.8%20Error%20Metrics%20Summary%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(error%2C%20np%2C%20residuals_flat)%3A%0A%20%20%20%20mae%20%3D%20np.mean(error)%0A%20%20%20%20rmse%20%3D%20np.sqrt(np.mean(error**2))%0A%20%20%20%20max_error%20%3D%20np.max(error)%0A%20%20%20%20residual_l2%20%3D%20np.linalg.norm(residuals_flat)%0A%0A%20%20%20%20error_data%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%5B%22Mean%20Absolute%20Error%20(MAE)%22%2C%20f%22%7Bmae%3A.6e%7D%22%5D%2C%0A%20%20%20%20%20%20%20%20%5B%22Root%20Mean%20Square%20Error%20(RMSE)%22%2C%20f%22%7Brmse%3A.6e%7D%22%5D%2C%0A%20%20%20%20%20%20%20%20%5B%22Maximum%20Error%22%2C%20f%22%7Bmax_error%3A.6e%7D%22%5D%2C%0A%20%20%20%20%20%20%20%20%5B%22PDE%20Residual%20L2%20Norm%22%2C%20f%22%7Bresidual_l2%3A.6e%7D%22%5D%2C%0A%20%20%20%20%5D%0A%20%20%20%20return%20(error_data%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(error_data%2C%20mo)%3A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20%7C%20Metric%20%7C%20Value%20%7C%0A%20%20%20%20%7C--------%7C-------%7C%0A%20%20%20%20%7Bchr(10).join(f%22%7C%20%7Brow%5B0%5D%7D%20%7C%20%7Brow%5B1%5D%7D%20%7C%22%20for%20row%20in%20error_data)%7D%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20%23%23%23%20Key%20Features%20of%20this%20PINN%20Implementation%0A%0A%20%20%20%20%E2%9C%85%20**Multi-term%20Loss%20Function**%0A%20%20%20%20-%20PDE%20residual%20enforces%20heat%20equation%20at%20collocation%20points%0A%20%20%20%20-%20Initial%20condition%20loss%20ensures%20correct%20starting%20temperature%20distribution%0A%20%20%20%20-%20Boundary%20condition%20losses%20maintain%20fixed%20boundary%20temperatures%0A%0A%20%20%20%20%E2%9C%85%20**Automatic%20Differentiation**%0A%20%20%20%20-%20First-order%20derivatives%3A%20%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20x%7D%24%2C%20%24%5Cfrac%7B%5Cpartial%20u%7D%7B%5Cpartial%20t%7D%24%0A%20%20%20%20-%20Second-order%20derivative%3A%20%24%5Cfrac%7B%5Cpartial%5E2%20u%7D%7B%5Cpartial%20x%5E2%7D%24%0A%20%20%20%20-%20Computed%20using%20PyTorch's%20autograd%20with%20%60create_graph%3DTrue%60%0A%0A%20%20%20%20%E2%9C%85%20**Validation%20Against%20Analytical%20Solution**%0A%20%20%20%20-%20Exact%20solution%3A%20%24u(x%2Ct)%20%3D%20%5Csin(%5Cpi%20x)%20e%5E%7B-%5Cpi%5E2%20%5Calpha%20t%7D%24%0A%20%20%20%20-%20Provides%20ground%20truth%20for%20error%20analysis%0A%0A%20%20%20%20%23%23%23%20Strengths%0A%0A%20%20%20%20-%20**No%20mesh%20required**%3A%20Unlike%20finite%20difference%2Felement%20methods%0A%20%20%20%20-%20**Smooth%20solutions**%3A%20Neural%20network%20provides%20continuous%20interpolation%0A%20%20%20%20-%20**Physics-informed**%3A%20Satisfies%20governing%20equations%20during%20training%0A%0A%20%20%20%20%23%23%23%20Limitations%0A%0A%20%20%20%20-%20**Computational%20cost**%3A%20Training%20can%20be%20slow%20for%20complex%20PDEs%0A%20%20%20%20-%20**Hyperparameter%20sensitivity**%3A%20Loss%20weights%20affect%20convergence%0A%20%20%20%20-%20**Local%20minima**%3A%20May%20require%20multiple%20training%20runs%0A%0A%20%20%20%20%23%23%23%20Extensions%0A%0A%20%20%20%20-%202D%2F3D%20heat%20equations%0A%20%20%20%20-%20Time-dependent%20boundary%20conditions%0A%20%20%20%20-%20Nonlinear%20PDEs%20(reaction-diffusion%2C%20Burgers'%20equation)%0A%20%20%20%20-%20Inverse%20problems%20(learning%20unknown%20parameters)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
6d1c17ff423c89d0e9e96f532ec2a648